package com.qymerge.manage.core.utils;

import com.qymerge.manage.core.constant.ParamKey;
import com.google.gson.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;

/**
 * Desc
 * User cong.li
 * Date 2017/4/5
 * Time 10:17
 */
public class GsonUtil {

    /**
     * 时间戳
     */
    public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 创建GSON
     *
     * @return
     */
    public static Gson getGson() {
        return new GsonBuilder().serializeNulls().setDateFormat(DATETIME_FORMAT).
                create();
    }

    /**
     * 创建GSON
     *
     * @return
     */
    public static Gson getGson(String dataFormat) {
        return new GsonBuilder().serializeNulls().setDateFormat(dataFormat).
                create();
    }

    /**
     * 将对象转化为字符串
     *
     * @param obj
     * @return
     */
    public static String Object2Json2(Object obj) {
        return getGson().toJson(obj);
    }

    /**
     * 将对象转化为字符串
     *
     * @param obj
     * @return
     */
    public String Object2Json2(String dateFormat, Object obj) {
        return getGson(dateFormat).toJson(obj);
    }

    /**
     * 将对象转化为字符串(泛型实现)
     *
     * @return
     */
    public static <T> String t2Json2(T t) {
        return getGson().toJson(t);
    }

    /**
     * 将对象转化为字符串(泛型实现)
     *
     * @return
     */
    public static <T> String t2Json2(String dateFormat, T t) {
        return getGson(dateFormat).toJson(t);
    }

    /**
     * 将对象转化为字符串(泛型实现)
     *
     * @return
     */
    public static <T> String t2Json2(T t, boolean serializeNulls, boolean executeField) {
        return getGsonBuild(DATETIME_FORMAT, serializeNulls, executeField).create().toJson(t);
    }

    /**
     * 创建GSONBuild
     *
     * @param dataFormat
     * @return
     */
    public static GsonBuilder getGsonBuild(String dataFormat, boolean serializeNulls, boolean excludeFieldsWithoutExposeAnnotation) {
        if (excludeFieldsWithoutExposeAnnotation) {
            return getGsonBuild(dataFormat, serializeNulls).excludeFieldsWithoutExposeAnnotation();
        }
        return getGsonBuild(dataFormat, serializeNulls);
    }

    /**
     * 创建GSONBuild
     *
     * @return
     */
    public static GsonBuilder getGsonBuild() {
        return new GsonBuilder().setDateFormat(DATETIME_FORMAT);
    }

    /**
     * 创建GSONBuild
     *
     * @param dataFormat
     * @return
     */
    public static GsonBuilder getGsonBuild(String dataFormat) {
        if (null != dataFormat && !"".equals(dataFormat)) {
            return getGsonBuild();
        }
        return getGsonBuild().setDateFormat(dataFormat);
    }

    /**
     * 创建GSONBuild
     *
     * @param dataFormat
     * @return
     */
    public static GsonBuilder getGsonBuild(String dataFormat, boolean serializeNulls) {
        if (serializeNulls) {
            return new GsonBuilder().setDateFormat(dataFormat).serializeNulls();
        }
        return getGsonBuild(dataFormat);
    }

    /**
     * 将字符转化为对象
     *
     * @param <T>
     * @param jsonString
     * @param clazz
     * @return
     */
    public static <T> T json2T(String jsonString, Class<T> clazz) {
        return getGson().fromJson(jsonString, clazz);
    }


    /**
     * 将字符转化为对象
     *
     * @param <T>
     * @param jsonString
     * @param type
     * @return
     */
    public static <T> T json2T(String jsonString, Type type) {
        return getGson().fromJson(jsonString, type);
    }

    /**
     * 将字符转化为对象
     *
     * @param <T>
     * @param jsonString
     * @param type
     * @return
     */
    public static <T> T json2T(HttpServletRequest request, String jsonString, Type type) {
        if (request != null) {
            String contentEncodinng = request.getHeader("Content-Encoding");
            if (contentEncodinng != null && contentEncodinng.toLowerCase().contains("gzip")) {
                try {
                    BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
                    String line = null;
                    StringBuffer sb = new StringBuffer();
                    while ((line = br.readLine()) != null) {
                        sb.append(line);
                    }
                    jsonString = sb.toString();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        try {
            String data = URLDecoder.decode(jsonString, "UTF-8");
            if (data.startsWith("parameters=")) {
                data = data.replace("parameters=", "");
            }
            return getGson().fromJson(data, type);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return getGson().fromJson(ParamKey.In.dlt_parameters, type);
    }


    /**
     * 将字符转化为对象
     *
     * @param <T>
     * @param jsonString
     * @param clazz
     * @return
     */
    public static <T> T json2T(String dateFormat, String jsonString, Class<T> clazz) {
        return getGson(dateFormat).fromJson(jsonString, clazz);
    }

    /**
     * 将字符串数组转化为对象集合
     *
     * @param <T>
     * @param jsonStr
     * @param type
     * @return
     */
    public static <T> List<T> json2Collection(String jsonStr, Type type) {
        return getGson().fromJson(jsonStr, type);
    }

    /**
     * map转成成json字符串
     * 解决字符串long成为double的问题
     *
     * @param map
     * @return
     */
    public static String map2Json(Map map) {
        Gson gson = new GsonBuilder().registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
            @Override
            public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
                if (src == src.longValue())
                    return new JsonPrimitive(src.longValue());
                return new JsonPrimitive(src);
            }
        }).create();
        return gson.toJson(map);
    }

}
